Skip to content

Exercises

Controlled Country Picker

The “Big List O’ Countries” select is a staple of e-commerce sites. Let's build one!

Using the data provided in the COUNTRIES object, create a <select> tag with options for every country. Bind this <select> tag to the provided country state variable.

Acceptance Criteria:

  • Use the COUNTRIES constant to dynamically generate the set of <option> elements.
  • There should be a "blank" option, selected by default. It shouldn't default to the first country in the list.
  • The indicator at the bottom should update when the user changes their selected country.
  • No warnings in the dev console

Code Playground

import React from 'react';

import { COUNTRIES } from './data';

/*
“COUNTRIES” is a dictionary-like object
with the following shape:

{
AF: "Afghanistan",
AL: "Albania",
DZ: "Algeria",
}
*/

function App() {
const [
country,
setCountry,
] = React.useState('');

return (
<form>
<fieldset>
<legend>Shipping Info</legend>
<label htmlFor="country">
Country:
</label>
<select
id="country"
name="country"
>
{/* TODO: Options here! */}
</select>
</fieldset>

<p className="country-display">
Selected country: {country}
</p>

<button>Submit</button>
</form>
);
}

export default App;

Solution:

Two-Factor Authentication

Two-factor authentication has quickly become a best practice in terms of securing logins for highly-sensitive accounts. The most common form I've seen is that the user is prompted to enter a short code, generated from an app.

In this exercise, we'll build this form!

Acceptance Criteria:

  • The input's value should be held in React state.
  • When the user submits their code, a window.alert should let them know whether it's correct or not, by comparing their submitted value with the CORRECT_CODE constant.
  • A <form> tag should be used.

Code Playground

import React from 'react';

const CORRECT_CODE = '123456';

function TwoFactor() {
return (
<>
<label htmlFor="auth-code">
Enter authorization code:
</label>
<div className="row">
<input
id="auth-code"
type="text"
required={true}
maxLength={6}
/>
<button>Validate</button>
</div>
</>
);
}

export default TwoFactor;

Solution:

Generative Art

In this exercise, we're building a tool to produce generative art!

The tool is nearly complete, but the form controls need to be wired up. Your job is to connect the React state to the form controls, so that tweaking the controls will update the art.

Acceptance Criteria:

  • The range slider should be bound to the numOfLines state.
  • The select control should be bound to the colorTheme state.
  • The radio buttons should be bound to the shape state.
  • The radio button labels should work correctly. The user should be able to click the text "Polygons" to select that option.
  • The inputs should conform to HTML standards (eg. radio buttons should be grouped using the “name” attribute).

Note: All of your changes should happen in App.js. The other files are shown in case you're curious how it works, but you can safely ignore them and focus exclusively on App.js.

Code Playground

import React from 'react';

import GenerativeArt from './GenerativeArt';

function App() {
const [numOfLines, setNumOfLines] = React.useState(5);

/*
Accepted values:
- basic
- monochrome
- froot-loops
- spooky
*/
const [colorTheme, setColorTheme] = React.useState('basic');

/*
Accepted values:
- circles
- polygons
*/
const [shape, setShape] = React.useState('circles');
return (
<>
<GenerativeArt
numOfLines={numOfLines}
colorTheme={colorTheme}
shape={shape}
/>
<form>
<fieldset>
<legend>Controls</legend>
<div className="row">
<div className="col">
<label
htmlFor="num-of-lines"
className="control-heading"
>
Number of Lines:
</label>
<input
id="num-of-lines"
type="range"
min="1"
max="15"
/>
</div>
</div>
<div className="row">
<div className="col">
<label
className="control-heading"
htmlFor="color-theme"
>
Color Theme:
</label>
<select id="color-theme">
<option value="basic">
Basic
</option>
<option value="monochrome">
Monochrome
</option>

Solution:

Video Summary

  • We can wire up our numOfLines slider as if it was a text input, setting value and onChange
  • Similarly, the colorMode select can be wired up by passing value and onChange to the parent <select> tag (not touching the options)
  • The radio buttons require a bit of fixing, before we can get to the React state stuff:
    • We need to add a name so that the two radio buttons function as a group, so that only one can be selected at a time
    • We need to add an id and an htmlFor so that the label functions properly
  • To wire them up, we need to add a value prop, but unlike with <select> and <input>, value isn't the React state-binding attribute. Instead, value specifies what each option should hold.
    • Think of it like how the value property works on <option> inside a <select>.
  • To start binding to React state, we need to add a checked property to each one. This property is a boolean value, depending on whether the current option should be selected or not.
  • Finally, we add an onChange handler. This works very similar to the other inputs we've seen.
  • Don't neglect the “value” prop! While it can be skipped by specifying a string in the onChange handler, this is not recommended, as it deviates from DOM specifications, and affects the ability for this form to work without React.